package com.pyp.kuaishou.service;

import com.pyp.kuaishou.model.StorePlatformConfig;
import com.pyp.kuaishou.repository.StorePlatformConfigRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import com.github.kwai.open.api.KwaiOpenOauthApi;
import com.github.kwai.open.request.AccessTokenRequest;
import com.github.kwai.open.response.AccessTokenResponse;
import com.github.kwai.open.request.RefreshTokenRequest;
import com.github.kwai.open.response.RefreshTokenResponse;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Value;

/**
 * 作者: lauJinyu
 * 业务层：快手授权逻辑，负责生成授权URL、处理回调、保存token
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class KSAuthService {

    private final StorePlatformConfigRepository configRepository;
    private final KSPublishService ksPublishService;
    // private final RestTemplate restTemplate = new RestTemplate(); // 已弃用：改用官方SDK

    // 快手授权地址：根据文档拼接
    // 网页/H5授权获取code
    private static final String AUTHORIZE_URL = "https://open.kuaishou.com/oauth2/authorize"; // <docs>
    // 通过code换取access_token（保留以兼容旧实现的常量，但不再直接使用）
    private static final String ACCESS_TOKEN_URL = "https://open.kuaishou.com/oauth2/access_token"; // <docs>

    // 从配置注入回调地址和scope
    @Value("${kuaishou.api.redirect-uri}")
    private String redirectUri;

    @Value("${kuaishou.api.scope:user_info,user_base,user_video_publish}")
    private String scope;

    /**
     * 构造授权URL（快手要求 state 传递自定义值，这里用 app_id）
     * 作者: lauJinyu
     */
    public String buildAuthorizeUrl(String appId) {
        String state = appId;
        String url = UriComponentsBuilder.fromHttpUrl(AUTHORIZE_URL)
                .queryParam("app_id", appId)
                .queryParam("scope", scope)
                .queryParam("response_type", "code")
                .queryParam("redirect_uri", redirectUri)
                .queryParam("state", state)
                .build(true).toUriString();
        log.info("authorizeUrl: {} | redirectUri: {} | scope: {}", url, redirectUri, scope);
        return url;
    }

    /**
     * 处理授权回调（无持久化版本）
     * 作者: lauJinyu
     */
    public Map<String, Object> handleCallback(String code, String state) {
        Map<String, Object> result = new HashMap<>();
        
        if (code == null || state == null) {
            result.put("success", false);
            result.put("message", "Missing code or state");
            return result;
        }
        
        try {
            // 从state中解析appId
            String appId = state;
            
            // 查找配置记录获取app_secret（仅获取app_secret，不存储token）
            Optional<StorePlatformConfig> configOpt = configRepository.findByAppId(appId);
            if (!configOpt.isPresent()) {
                result.put("success", false);
                result.put("message", "未找到应用配置记录，appId: " + appId);
                return result;
            }
            
            StorePlatformConfig config = configOpt.get();
            String appSecret = config.getAppSecret();
            
            // 调用快手SDK获取access_token（仅内存操作）
            Map<String, Object> tokenResponse = getAccessTokenFromKuaishou(code, appId, appSecret);
            
            if (!(Boolean) tokenResponse.get("success")) {
                return tokenResponse;
            }
            
            String accessToken = (String) tokenResponse.get("access_token");
            
            result.put("success", true);
            result.put("access_token", accessToken);
            result.put("message", "授权成功，获取到access_token");
            
            log.info("成功完成授权回调，appId: {}，不进行token持久化", appId);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "授权失败: " + e.getMessage());
            log.error("处理授权回调失败", e);
        }
        
        return result;
    }

    /**
     * 处理授权回调并自动发布视频
     * 作者: lauJinyu
     */
    public Map<String, Object> handleCallbackAndPublish(String code, String state) {
        Map<String, Object> result = new HashMap<>();
        
        log.info("handleCallbackAndPublish - code: {}, state: {}", code, state);
        
        if (code == null || state == null) {
            result.put("success", false);
            result.put("message", "Missing code or state parameters");
            return result;
        }
        
        // 验证state格式，确保包含下划线分隔符
        if (!state.contains("_")) {
            result.put("success", false);
            result.put("message", "Invalid state format. Expected format: appId_storeId");
            log.error("Invalid state format: {}, expected format: appId_storeId", state);
            return result;
        }
        
        try {
            // 1. 从state中解析appId和storeId
            String[] stateParts = state.split("_", 2); // 限制分割为2部分，防止storeId中包含下划线
            if (stateParts.length != 2 || stateParts[0].isEmpty() || stateParts[1].isEmpty()) {
                result.put("success", false);
                result.put("message", "Invalid state format. Both appId and storeId must be non-empty");
                log.error("Invalid state parts: {}, expected 2 non-empty parts", java.util.Arrays.toString(stateParts));
                return result;
            }
            
            String appId = stateParts[0];
            String storeId = stateParts[1];
            
            log.info("Parsed state - appId: {}, storeId: {}", appId, storeId);
            
            // 2. 处理授权回调，获取access_token
            Map<String, Object> authResult = handleCallback(code, state);
            
            if (!(Boolean) authResult.get("success")) {
                return authResult;
            }
            
            // 3. 获取access_token用于发布
            String accessToken = (String) authResult.get("access_token");
            
            // 4. 调用发布服务进行视频发布，传入appId
            Map<String, Object> publishResult = ksPublishService.publishVideo(accessToken, appId);
            
            // 5. 合并结果
            Map<String, Object> finalResult = new HashMap<>();
            finalResult.put("auth_result", authResult);
            finalResult.put("publish_result", publishResult);
            finalResult.put("success", (Boolean) authResult.get("success") && (Boolean) publishResult.get("success"));
            finalResult.put("message", "Authorization and publish completed");
            finalResult.put("app_id", appId);
            finalResult.put("store_id", storeId);
            
            log.info("handleCallbackAndPublish completed successfully for appId: {}, storeId: {}", appId, storeId);
            return finalResult;
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "处理失败: " + e.getMessage());
            log.error("handleCallbackAndPublish failed", e);
        }
        
        return result;
    }

    /**
     * 使用快手官方SDK获取access_token
     * 作者: lauJinyu
     */
    private Map<String, Object> getAccessTokenFromKuaishou(String code, String appId, String appSecret) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 1) 构建SDK实例并初始化应用ID（使用静态init避免无参构造）
            KwaiOpenOauthApi oauthApi = KwaiOpenOauthApi.init(appId);
            
            // 2) 组装请求对象（SDK定义的请求体）
            AccessTokenRequest req = new AccessTokenRequest(code, appSecret);
            
            // 3) 调用SDK方法获取响应
            AccessTokenResponse resp = oauthApi.getAccessToken(req);
            if (resp == null) {
                result.put("success", false);
                result.put("message", "SDK返回为空响应");
                return result;
            }
            
            String accessToken = resp.getAccessToken();
            if (accessToken == null || accessToken.isEmpty()) {
                result.put("success", false);
                result.put("message", "未获取到access_token，可能是授权code无效或已过期");
                return result;
            }
            
            // 4) 解析可选字段
            String refreshToken = resp.getRefreshToken();
            Long expiresIn = null;
            try {
                // SDK方法签名显示getExpiresIn返回Long/long
                expiresIn = resp.getExpiresIn();
            } catch (Exception ignore) {
                // 兼容潜在的空指针或类型差异
            }
            
            // 5) 封装统一返回
            result.put("success", true);
            result.put("access_token", accessToken);
            if (refreshToken != null) {
                result.put("refresh_token", refreshToken);
            }
            if (expiresIn != null) {
                result.put("expires_in", expiresIn);
            }
            
            log.info("[SDK] 成功获取快手access_token，appId: {}，是否包含expires_in: {}", appId, expiresIn != null);
        } catch (Exception e) {
            // SDK内部已处理HTTP调用，这里统一捕获异常并返回统一错误信息
            result.put("success", false);
            result.put("message", "调用快手SDK异常: " + e.getMessage());
            log.error("调用快手SDK获取access_token失败", e);
        }
        return result;
    }

    /**
     * 使用快手官方SDK刷新access_token
     * 作者: lauJinyu
     */
    public Map<String, Object> refreshAccessToken(String appId, String refreshToken) {
        Map<String, Object> result = new HashMap<>();
        try {
            Optional<StorePlatformConfig> configOpt = configRepository.findByAppId(appId);
            if (!configOpt.isPresent()) {
                result.put("success", false);
                result.put("message", "未找到应用配置记录，appId: " + appId);
                return result;
            }
            String appSecret = configOpt.get().getAppSecret();

            // 使用静态init避免无参构造
            KwaiOpenOauthApi oauthApi = KwaiOpenOauthApi.init(appId);

            RefreshTokenRequest req = new RefreshTokenRequest(refreshToken, appSecret);
            RefreshTokenResponse resp = oauthApi.refreshToken(req);
            if (resp == null) {
                result.put("success", false);
                result.put("message", "SDK返回为空响应");
                return result;
            }

            String newAccessToken = resp.getAccessToken();
            if (newAccessToken == null || newAccessToken.isEmpty()) {
                result.put("success", false);
                result.put("message", "未获取到新的access_token，可能是refresh_token无效或已过期");
                return result;
            }

            result.put("success", true);
            result.put("access_token", newAccessToken);
            if (resp.getRefreshToken() != null) {
                result.put("refresh_token", resp.getRefreshToken());
            }
            if (resp.getExpiresIn() != null) {
                result.put("expires_in", resp.getExpiresIn());
            }
            if (resp.getRefreshTokenExpiresIn() != null) {
                result.put("refresh_token_expires_in", resp.getRefreshTokenExpiresIn());
            }

            log.info("[SDK] 刷新access_token成功，appId: {}", appId);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "刷新access_token异常: " + e.getMessage());
            log.error("刷新access_token失败", e);
        }
        return result;
    }

    /**
     * 废弃的方法：原本用于从数据库获取token，现在所有token操作都是实时的
     * 作者: lauJinyu
     */
    @Deprecated
    public Map<String, Object> getOrRefreshToken(String appId) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        result.put("message", "此接口已废弃。请使用实时授权流程：用户授权 -> 快手回调 -> 获取token并立即使用");
        log.warn("调用了已废弃的getOrRefreshToken方法，appId: {}", appId);
        return result;
    }
}